/* 
 * File:   MundoSBS.h
 * Author: lucia
 *
 * Created on 6 de octubre de 2014, 19:24
 */

#ifndef MUNDOSBS_H
#define	MUNDOSBS_H


#include <cstdlib>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include "FireShooterEnemy.h"



#include <Box2D/Box2D.h>
#include <JSON/json.hh>
#include <thread>
#include <vector>
#include <queue>
#include <list>


#include "WorldElement.h"
#include "ServerSocket.h"
#include "Player.h"
#include "../Controller/SBSLog.h"
#include "../Define/FileWindow.h"
#include "../Define/Structs.h"
#include "ObjFactory.h"
#include "Rectangle.h"
#include "Circle.h"
#include "Character.h"
#include "Polygon.h"
#include "Trapezium.h"
#include "Parallellogram.h"
#include "StandardEnemy.h"
#include "FireShooterEnemy.h"
#include "Bonus.h"
#include "FireShooterEnemy.h"
#include "StandardEnemy.h"
#include "SnowBall.h"
#include "Boss.h"
using namespace std;

class MundoSBS {
private:
    struct sockaddr_in clientAddress;
    int socketClient;
    ServerSocket server;
    
    // almacenamos el nivel 1
    vector<struct ObjectInit> worldObjects;    

    vector<WorldElement*> staticBodys;
    vector<WorldElement*> dynamicBodys;
    vector<WorldElement*> auxPlayers;
    vector<WorldElement*> ground;
    //    vector<Enemy*> enemies; #NOTA: old
    vector <FireShooterEnemy* >fireShooterEnemy;
    vector <StandardEnemy* >standardEnemy;
    vector<Bonus*> bonus;

    bool running;
    bool readyToReload;
    std::thread threadConection;

    list <Player*> players;
    list <struct ContenedorSocket> futurePlayers;   // almaceno los sockets de los futuros players
    list <Player*> waitingList;

    SBSLog* myLogFile;
    FileWindow *data;
    FileWindow *data2;
    b2World *world;
    int playerCounter; //cantidad de jugadores conectados
    int maxPlayers; //cantidad maxima de jugadores que se permiten
    ObjFactory* objFact;

    void startConection();
    void sendMap(); //#TODO hay que eliminarlo.
    //SHOOT
    list <Bullet*>bulletsList;
    list <Bullet*>bulletsOld;
    int contadorPAU;
    int muertos;
    
    int reloadGame;
    
    Boss* theBoss;

    bool marioAvailable;
    bool yoshiAvailable;
    bool luigiAvailable;
    bool tazAvailable;    
    
public:
    
    bool reloadLevel;

    MundoSBS();
    MundoSBS(const MundoSBS& orig);
    virtual ~MundoSBS();
    void close();
    void initServer(char * address, int port);
    void getConection();
    list <Bullet*> getBulletList();
    list <Player*> *getPlayers();

    bool arePlayersWaiting();
    bool areFuturesPlayers();

    struct ContenedorSocket getFirstFuturePlayer();
    
    void actualizePlayerList();
    void createWorld();
    void deleteWorld();
    int cantPlayersInit();
    bool areEnemiesAlive();
    bool isBossAlive();
    void resetPlayers();
    void setReloadLevel(bool state);

    b2World *getWorld();
    struct sockaddr_in getClientAddr(); //es necesario este metodo?
    void decreaseCount();
    //Lanza hilos por cada usuario que se encuentra en estado de jugar
    void runThreads();

    //Lectura de archivo de JSON.
    void initData(int argc, char** args);
    void initData2(int argc, char** args);
    void clean();

    // carga todos los elementos al mundo de Box2D desde el JSON
    // carga los vectores staticBodys y dynamicBodys
    void initGame();
    void initGame2();

    // envio inicial de elementos del mundo Box2D
    // -1 en caso de error.
    void createPlayer(int socket, struct Jugador myPlayer);
    int initPlayer(Player &player); //Inicializa los jugadores que se conectaron.
    void sendPlayer();

    void refusePlayer(int socket);

    int playerAlreadyExist(string name); //devuelve el id del player 
    struct Element reloadPlayer(string name);

    void killBodyPlayer(Player* player);
    void killEnemy(Enemy* enemy);
    void checkChanges();

    bool playersAreReady();
    bool playersReadyToReload();
    bool gameOver();

    ServerSocket getServer();

    // como el setUpdatedData pero sin filtros
    void sendInitialWorld(Player * player); //para enviar los dinamicos
    void sendInitialWorldStatics(Player * player);//para enviar los estaticos
    void setUpdatedData(Player* player);

    void makeEnemiesMove();
    void makeBossMove();
    //shoot
    void setBullets(SnowBall *snowBall);
    void setUpdateBullet();

    void addNewBonus(float posX, float posY);
    void deleteBonus();
    void deleteOldBonus();
    void setMuertos(); //incremento la cantidad de muertos.
    bool isGameOver();
    
    void erasePlayersNotInit();
    
};

#endif	/* MUNDOSBS_H */

